﻿using System;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows.Controls;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Utilities;

namespace RegionExtension
{
    [Export(typeof(IWpfTextViewCreationListener))]
    [ContentType("text")]
    [TextViewRole(PredefinedTextViewRoles.Document)]
    internal class RegionExtensionViewCreationListener : IWpfTextViewCreationListener
    {
        [Import]
        internal IViewTagAggregatorFactoryService ViewTagAggregatorFactoryService { get; set; }

        private ITextView textView;

        private ITagAggregator<IntraTextAdornmentTag> tagAggregator;

        public void TextViewCreated(IWpfTextView textView)
        {
            this.textView = textView;
            this.tagAggregator = this.ViewTagAggregatorFactoryService.CreateTagAggregator<IntraTextAdornmentTag>(this.textView);
            this.tagAggregator.BatchedTagsChanged += new EventHandler<BatchedTagsChangedEventArgs>(OnBatchedTagsChanged);
        }

        private void OnBatchedTagsChanged(object sender, BatchedTagsChangedEventArgs e)
        {
            var list = new NormalizedSnapshotSpanCollection(e.Spans.SelectMany(x => x.GetSpans(this.textView.TextBuffer)));
            if (list.Count != 0)
            {
                var tags = this.tagAggregator.GetTags(list);

                foreach (var tag in tags)
                {
                    if (tag.Tag.Adornment is OutliningCollapsedAdornmentControl)
                    {
                        var spans = tag.Span.GetSpans(this.textView.TextSnapshot);
                        if (spans.Count == 0)
                        {
                            continue;
                        }

                        string comment;
                        if (TryGetComment(spans[0], out comment))
                        {
                            ((OutliningCollapsedAdornmentControl)tag.Tag.Adornment).Content = comment;
                            tag.Tag.Adornment.GetChild<TextBlock>().Text = comment;
                        }
                    }
                }
            }
        }

        private bool TryGetComment(Span span, out string comment)
        {
            int start = span.Start;
            int end = span.End;
            ITextSnapshotLine line;
            int count = 0;
            while (start < end && count < 3)
            {
                line = this.textView.TextSnapshot.GetLineFromPosition(start);
                if (line.Start.Position < start)
                {
                    start = line.Start.Position;
                }

                string text = line.GetText();
                if (text.IndexOf("#region") > -1)
                {
                    break;
                }

                if (text.IndexOfAny(new char[] { '/' }) > -1)
                {
                    var metchs = Regex.Match(text, @"//\s*(?<comment>.+)");
                    if (metchs.Success)
                    {
                        comment = metchs.Groups["comment"].Value.Left(20, "...");
                        return true;
                    }
                }

                start += line.Length + line.LineBreakLength;
                count++;
            }

            comment = null;
            return false;
        }
    }
}